Skip to content

feat(X402-44): JSON API stability — snapshot test + contract doc + versioning rule#78

Merged
fardinvahdat merged 1 commit into
mainfrom
feat/X402-44-json-api-stability
May 22, 2026
Merged

feat(X402-44): JSON API stability — snapshot test + contract doc + versioning rule#78
fardinvahdat merged 1 commit into
mainfrom
feat/X402-44-json-api-stability

Conversation

@fardinvahdat
Copy link
Copy Markdown
Owner

Summary

X402-44 — locks bazaar-check --log json as a documented public API contract per ADR-004 Pillar 2. Three deliverables land together. Lands BEFORE D.2/D.3 so those tickets are forced through the snapshot contract from the start.

What this PR delivers

1. Contract doc: src/bazaar/json-api.md

Envelope shape, per-check detail keys, verdict discriminator, exit-code contract, stability rules, regeneration workflow. The canonical reference for any consumer (mapper integrations, agent filters, future bazaar-aware tools) taking a runtime dependency on the JSON output.

2. Frozen exemplar: tests/fixtures/bazaar/json-api-snapshot.json

Hand-rolled deterministic JSON capturing one canonical looks_correct run with all four checks passing. Regenerated only when JSON shape is intentionally changed (workflow documented in the contract doc).

3. Snapshot test: tests/integration/bazaar-check-json-api.test.ts

6 tests catch the four classes of shape drift:

Test What it catches
deep-equal field renames, removals, additions, value drift
top-level key order reordering of envelope keys
per-result key order reordering of CheckResult shape per check
verdict key order reordering of discriminator + per-kind fields
4-canonical-checks accidental removal of a check by name
fixture-is-valid-JSON basic sanity

The deterministic fetcher in the test produces exactly the shape in the fixture; any divergence fails the test with a regenerate-snapshot instruction.

Versioning rule (committed per ADR-004 Pillar 2)

  • Additive changes (new optional fields, new check names, new verdict.kind values, new detail.* keys) → MINOR + ### JSON API CHANGELOG entry
  • Shape-breaking changes (renames, removals, type changes, fixed-position reordering) → MAJOR + deprecation cycle + integrator notice
  • Exit-code contract preserved across all minor versions (0 looks_correct / 2 implementation_issue / 3 upstream_issue). D.3's upstream_stuck composite (X402-46) will roll up to exit code 3, NOT introduce exit code 4 — verdict prose carries the granularity.

Docs updates

  • README gains a "JSON API (v0.3.2+) — --log json is a public contract" section under the bazaar-check documentation, linking to the contract doc.
  • CONTRIBUTING.md gains a "JSON API discipline" section with a PR self-check covering shape changes.

No shape changes to the JSON envelope this PR

The exemplar captures the shape after D.4 + D.5 land, including the additive detail.variant (D.5) and well-known skip message (D.4). This PR establishes the contract; the shape itself is unchanged.

Acceptance criteria (X402-44)

  • tests/fixtures/bazaar/json-api-snapshot.json exists with current v0.3.2 JSON shape captured
  • tests/integration/bazaar-check-json-api.test.ts asserts the snapshot matches; tests fail on intentional shape change with a clear regenerate-snapshot instruction (file header documents the regen workflow)
  • src/bazaar/json-api.md documents the contract (top-level keys, each facet's shape, versioning rule)
  • README has a "JSON API" section linking to src/bazaar/json-api.md
  • CHANGELOG.md [Unreleased] has a ### JSON API subsection covering the new commitments + additive changes from D.4/D.5
  • CONTRIBUTING.md has a section explaining the JSON API discipline + how to regenerate the snapshot
  • No new runtime dependencies (uses Node built-in node:fs like PR chore: capture TomSmart_ai 19-URL production set as v0.3.2 fixture bed #69's fixture test) — confirmed via check:publish-surface

Strict audit gate — abbreviated (user-in-loop mode)

  • Stage 1 pre-work: branched off 971ab4c (PR feat(X402-42): --endpoint <paid-url> per-route 402 probe mode (D.4) #77 D.4 merged HEAD); .gitignore WIP not staged
  • Stage 2 implementation: 3 new files + 3 modified docs (README + CONTRIBUTING + CHANGELOG); parallel-safe with everything downstream
  • Stage 3 correctness: ✅ typecheck + lint + 466 tests pass (was 460; +6 snapshot tests) + build + check:publish-surface 98 files / 369 KB / 0 devDep imports (under 400 KB cap)
  • Stage 4 edge cases: ≥10 incl. snapshot regeneration with malformed JSON, key reordering at each level, new field added by future code (deep-equal fails), new CHECK added (length mismatch fails), unicode in service names, optional fix field removal
  • Stage 5 gap check: all 7 X402-44 AC items satisfied; cross-references to ADR-004 Pillar 2 + X402-46 (D.3 upstream_stuck rollup decision) present in the contract doc
  • Stage 6 ship: this PR

What unblocks on merge

  • X402-45 (D.2 propagation diff) — can now add metadata_propagation facet AND the snapshot test will fail-loud unless the regen + CHANGELOG entry happen together
  • X402-46 (D.3 indexer-state probe) — same protection for indexer_state + upstream_stuck verdict
  • X402-47 (fixture consumption) — anchor-x402 multi-rail tests can reference the canonical shape

🤖 Generated with Claude Code

…rsioning rule

Locks `bazaar-check --log json` as a documented public API contract per
ADR-004 Pillar 2. Three deliverables:

- src/bazaar/json-api.md — envelope shape + per-check `detail` keys +
  verdict discriminator + exit-code contract + stability rules +
  regeneration workflow
- tests/fixtures/bazaar/json-api-snapshot.json — hand-rolled canonical
  exemplar of one deterministic looks_correct run
- tests/integration/bazaar-check-json-api.test.ts — 6 tests catch
  field renames, removals, additions, and reordering against the
  exemplar (deep-equal + per-result key-order + verdict key-order +
  4-canonical-check-names invariants)

Versioning rule committed:
- Additive (new optional fields, new check names, new verdict.kind
  values, new detail.* keys) → MINOR + ### JSON API CHANGELOG entry
- Shape-breaking (renames, removals, type changes, fixed-position
  reordering) → MAJOR + deprecation cycle + integrator notice
- Exit-code contract (0 looks_correct / 2 implementation_issue /
  3 upstream_issue) preserved across all minor versions; D.3's
  upstream_stuck will roll up to exit code 3, not a new code

Docs:
- README JSON API section under bazaar-check, links to the contract doc
- CONTRIBUTING.md JSON API discipline section with a PR self-check

No shape changes to the JSON envelope itself this PR — the exemplar
captures the shape after D.4 + D.5 land, including the additive
detail.variant (D.5) and well-known skip message (D.4).

TomSmart_ai's mapper-integration is the named consumer this contract
is committed to.

Tests: 466 total pass (was 460); 6 new snapshot tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
x402trace-dogfood Ready Ready Preview, Comment May 22, 2026 10:06pm

@fardinvahdat fardinvahdat merged commit 61de55e into main May 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant